import 'dart:math';

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';

import 'generated/l10n.dart';

class PasswordGenerator extends StatefulWidget {
  final bool isWindow;
  const PasswordGenerator({Key? key, this.isWindow = false}) : super(key: key);

  @override
  State<PasswordGenerator> createState() => _PasswordGenerateState();
}

class _PasswordGenerateState extends State<PasswordGenerator> {
  bool useUppercase = true;
  bool useLowercase = true;
  bool useNumber = true;
  String otherChars = '';
  static const commonChars = '!@#\$%^&*=-_';
  int length = 8;
  int count = 10;
  int rowCount = 0;

  TextEditingController charsController = TextEditingController();
  TextEditingController passwordController = TextEditingController();

  @override
  void initState() {
    super.initState();
  }

  Future<void> _showDialog(String message,
      {String? buttonText, String? title}) async {
    return showDialog<void>(
      context: context,
      barrierDismissible: false, // user must tap button!
      builder: (BuildContext context) {
        return AlertDialog(
          title: Text(title ?? S.of(context).alert),
          content: SingleChildScrollView(
            child: ListBody(
              children: <Widget>[
                Text(message),
              ],
            ),
          ),
          actions: <Widget>[
            TextButton(
              child: Text(buttonText ?? S.of(context).ok),
              onPressed: () {
                Navigator.of(context).pop();
              },
            ),
          ],
        );
      },
    );
  }

  void generatePassword() {
    if (length < 1) {
      _showDialog(
          S.of(context).password_length_greater.replaceFirst('%d', '1'));
      return;
    }
    if (count < 1) {
      _showDialog(
          S.of(context).generator_count_greater.replaceFirst('%d', '1'));
      return;
    }
    var allText = '';
    if (useUppercase) {
      allText += 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
    }
    if (useLowercase) {
      allText += 'abcdefghijklmnopqrstuvwxyz';
    }
    if (useNumber) {
      allText += '0123456789';
    }
    if (otherChars.isNotEmpty) {
      allText += otherChars;
    }
    if (allText.isEmpty) {
      _showDialog(S.of(context).character_repertoire_cannot_empty);
      return;
    }
    List<String> passwords = [];
    int allLength = allText.length;
    Random random = Random();
    for (int i = 0; i < count; i++) {
      String pass = '';
      for (int j = 0; j < length; j++) {
        pass += allText[random.nextInt(allLength)];
      }
      passwords.add(pass);
    }
    setState(() {
      rowCount = count;
      passwordController.text = passwords.join("\n");
    });
  }

  Widget settingBox() {
    return Column(
      mainAxisAlignment: MainAxisAlignment.spaceBetween,
      children: [
        ListTile(
          title: Text(S.of(context).contains_capital_letters),
          subtitle: Text(S.of(context).uppercase_characters_a_z),
          trailing: CupertinoSwitch(
            value: useUppercase,
            onChanged: (bool value) {
              setState(() {
                useUppercase = value;
              });
            },
          ),
          onTap: () {
            setState(() {
              useUppercase = !useUppercase;
            });
          },
        ),
        ListTile(
          title: Text(S.of(context).contains_lowercase_letters),
          subtitle: Text(S.of(context).lower_characters_a_z),
          trailing: CupertinoSwitch(
            value: useLowercase,
            onChanged: (bool value) {
              setState(() {
                useLowercase = value;
              });
            },
          ),
          onTap: () {
            setState(() {
              useLowercase = !useLowercase;
            });
          },
        ),
        ListTile(
          title: Text(S.of(context).contains_numbers),
          subtitle: Text(S.of(context).numbers_0_9),
          trailing: CupertinoSwitch(
            value: useNumber,
            onChanged: (bool value) {
              setState(() {
                useNumber = value;
              });
            },
          ),
          onTap: () {
            setState(() {
              useNumber = !useNumber;
            });
          },
        ),
        Padding(
          padding: EdgeInsets.fromLTRB(15, 0, 15, 0),
          child: TextField(
            onChanged: (String value) {
              otherChars = value;
            },
            controller: charsController,
            decoration: InputDecoration(
                labelText: S.of(context).other_characters,
                helperText: S.of(context).other_chars_includes,
                suffixIcon: IconButton(
                  icon: Icon(Icons.ac_unit),
                  onPressed: () {
                    charsController.text = commonChars;
                    otherChars = commonChars;
                  },
                )),
          ),
        ),
        Row(
          children: [
            Expanded(
              child: Padding(
                padding: EdgeInsets.fromLTRB(15, 0, 10, 0),
                child: TextField(
                  onChanged: (String value) {
                    length = int.tryParse(value) ?? 8;
                  },
                  decoration: InputDecoration(
                      labelText: S.of(context).password_length,
                      helperText:
                          S.of(context).default_length.replaceFirst('%d', '8')),
                ),
              ),
            ),
            Expanded(
              child: Padding(
                padding: EdgeInsets.fromLTRB(0, 0, 15, 0),
                child: TextField(
                  onChanged: (String value) {
                    count = int.tryParse(value) ?? 10;
                  },
                  decoration: InputDecoration(
                      labelText: S.of(context).generate_count,
                      helperText:
                          S.of(context).default_count.replaceFirst('%d', '10')),
                ),
              ),
            ),
          ],
        ),
        Padding(
          padding: EdgeInsets.fromLTRB(15, 10, 15, 10),
          child: Row(
            children: [
              Expanded(
                child: TextButton(
                  style: ButtonStyle(
                    foregroundColor: WidgetStateProperty.all(Colors.white),
                    backgroundColor: WidgetStateProperty.all(Colors.blueAccent),
                  ),
                  onPressed: () {
                    generatePassword();
                  },
                  child: Padding(
                      padding: EdgeInsets.symmetric(vertical: 10),
                      child: Text(S.of(context).generate)),
                ),
              ),
              SizedBox(
                width: 10,
              ),
              TextButton(
                style: ButtonStyle(
                  foregroundColor: WidgetStateProperty.all(Colors.black),
                  backgroundColor: WidgetStateProperty.all(Colors.grey),
                ),
                onPressed: () {
                  setState(() {
                    rowCount = 0;
                    passwordController.text = '';
                  });
                },
                child: Padding(
                    padding: EdgeInsets.symmetric(vertical: 10, horizontal: 20),
                    child: Text(S.of(context).clear)),
              ),
            ],
          ),
        ),
      ],
    );
  }

  Widget resultBox() {
    const style = TextStyle(
      fontSize: 18,
      height: 1.5,
    );
    return Column(
      children: [
        Expanded(
          child: Padding(
            padding: EdgeInsets.all(10),
            child: CupertinoTextField(
              textAlignVertical: TextAlignVertical.top,
              textAlign: TextAlign.start,
              minLines: null,
              maxLines: null,
              expands: true,
              readOnly: true,
              controller: passwordController,
              style: style,
              contextMenuBuilder: (context, editableTextState) {
                return CupertinoAdaptiveTextSelectionToolbar.editableText(
                    editableTextState: editableTextState);
              },
              prefix: Container(
                decoration: rowCount < 1
                    ? null
                    : BoxDecoration(
                        color: Color.fromRGBO(0, 0, 0, 0.1),
                        borderRadius: BorderRadius.only(
                            topLeft: Radius.circular(5.0),
                            bottomLeft: Radius.circular(5.0))),
                child: Align(
                  alignment: Alignment.center,
                  child: Padding(
                    padding: EdgeInsets.fromLTRB(5, 7, 0, 0),
                    child: Text(
                      [
                        '01',
                        '02',
                        '03',
                        '04',
                        '05',
                        '06',
                        '07',
                        '08',
                        '09',
                        '10',
                        '11',
                        '12',
                        '13',
                        '14',
                        '15',
                        '16',
                        '17',
                        '18',
                        '19',
                        '20',
                        '21',
                        '22',
                        '23',
                        '24',
                        '25',
                        '26',
                        '27',
                        '28',
                        '29',
                        '30',
                        '31',
                        '32',
                        '33',
                        '34',
                        '35',
                        '36',
                        '37',
                        '38',
                        '39'
                      ].sublist(0, rowCount).join("\n"),
                      style: style,
                      textAlign: TextAlign.start,
                    ),
                  ),
                ),
              ),
            ),
          ),
        )
      ],
    );
  }

  @override
  Widget build(BuildContext context) {
    return Padding(
      padding: EdgeInsets.all(10),
      child: Flex(
        direction: widget.isWindow ? Axis.horizontal : Axis.vertical,
        children: [
          SizedBox(
            width: widget.isWindow ? 350 : null,
            height: widget.isWindow ? null : 430,
            child: settingBox(),
          ),
          Expanded(
            child: resultBox(),
          )
        ],
      ),
    );
  }
}
